package com.autonavi.yunda.yunji.common.utils.http;

import com.autonavi.yunda.yunji.common.enums.ContentType;
import com.autonavi.yunda.yunji.common.utils.JsonUtils;
import com.google.common.collect.Maps;
import okhttp3.Headers;
import okhttp3.Response;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.util.CollectionUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author cizhong.wcs
 * @date 2022/1/26 2:29 下午
 */
public class HttpUtil {
    private static final String FILE = "file";

    private HttpUtil() {
    }


    public static Map<String, String[]> getParamsArrayMap(String urlParam) {
        Map<String, String[]> queryParams = Maps.newHashMap();
        if (Strings.isBlank(urlParam)) {
            return queryParams;
        }
        String[] params = urlParam.split("&");

        Stream.of(params)
                .map(param -> param.split("="))
                .collect(Collectors.groupingBy(array -> array[0], Collectors.mapping(arr -> Arrays.stream(arr).collect(Collectors.toList()).subList(1, arr.length).stream().collect(Collectors.joining("=")), Collectors.toList())))
                .forEach((k, v) -> queryParams.put(k, v.toArray(new String[0])));
        return queryParams;
    }

    public static Map<String, String> getParamsMapUrlDecode(String urlParam) {
        Map<String, String> queryParams = Maps.newHashMap();
        if (Strings.isBlank(urlParam)) {
            return queryParams;
        }
        String[] params = urlParam.split("&");
        queryParams = Stream.of(params)
                .map(param -> param.split("="))
                .collect(Collectors.toMap(
                        array -> urlDecode(array[0]),
                        array -> array.length > 1 ? urlDecode(array[1]) : ""
                ));
        return queryParams;
    }


    public static String getParamsString(Map<String, Object> queryParams) {
        if (MapUtils.isNotEmpty(queryParams)) {
            return queryParams.entrySet()
                    .stream()
                    .filter(en -> en.getValue() != null)
                    .map(en -> en.getKey() + "=" + en.getValue()).collect(Collectors.joining("&"));
        }
        return null;
    }

    public static String getParamsStringUrlEncoded(Map<String, Object> queryParams) {
        if (MapUtils.isNotEmpty(queryParams)) {
            return queryParams.entrySet()
                    .stream()
                    .filter(en -> en.getValue() != null)
                    .map(en -> urlEncode(en.getKey()) + "=" + urlEncode(en.getValue().toString())).collect(Collectors.joining("&"));
        }
        return null;
    }


    public static Map<String, String> getHeaders(Response response) {
        Map<String, String> headers = Maps.newHashMap();
        Headers resHeaders = response.headers();
        if (CollectionUtils.isEmpty(resHeaders.names())) {
            return headers;
        }
        resHeaders.names().forEach(name -> headers.put(name, resHeaders.get(name)));
        return headers;
    }

    public static String generateCurl(String url, Map<String, Object> paramMap, String method, Map<String, Object> bodyMap, Map<String, String> headers, ContentType contentType, Map<String, String> fileMarkMap) {
        StringBuilder curl = new StringBuilder();
        if (paramMap != null && !paramMap.isEmpty()) {
            url = url + "?" + getParamsStringUrlEncoded(paramMap);
        }
        curl.append(String.format("curl --request %s '%s' \\\n", method.toUpperCase(), url));
        if (!bodyMap.isEmpty() && ContentType.JSON.equals(contentType)) {
            headers.put("content-type", "application/json");
            curl.append(String.format("-d '%s'", JsonUtils.toString(bodyMap))).append(" \\\n");
        } else if (!bodyMap.isEmpty() && ContentType.FORM_URLENCODED.equals(contentType)) {
            curl.append(String.format("-d '%s'", getParamsStringUrlEncoded(bodyMap))).append(" \\\n");
            headers.put("content-type", "application/x-www-form-urlencoded");
        } else if (!bodyMap.isEmpty() && ContentType.MULTIPART_FORM.equals(contentType)) {
            bodyMap.forEach((k, v) -> {
                if (FILE.equals(fileMarkMap.get(k))) {
                    curl.append(String.format("--form '%s=@\"%s文件路径\"' \\\n", k, v));
                } else {
                    curl.append(String.format("--form '%s=\"%s\"' \\\n", k, v));
                }
            });
            headers.put("content-type", "multipart/form-data");
        }
        headers.forEach((k, v) -> curl.append(String.format("--header \"%s:%s\" \\\n", k, v)));
        String curlStr = curl.toString();
        if (curlStr.endsWith("\\\n")) {
            curlStr = curlStr.substring(0, curlStr.length() - 2);
        }
        return curlStr;
    }

    private static String urlEncode(String value) {
        if (value != null) {
            try {
                return URLEncoder.encode(value, "UTF8");
            } catch (UnsupportedEncodingException ignored) {
            }
        }
        return value;
    }

    private static String urlDecode(String value) {
        if (value != null) {
            try {
                value = URLDecoder.decode(value, "UTF8");
            } catch (UnsupportedEncodingException ignored) {
            }
        }
        return value;
    }
}
